{ End Bracket }
Experimenting with F#
Don Syme
After five years of guiding generics for the Microsoft® .NET Framework into Visual Studio® 2005, I've turned my attention to attempting to achieve a synthesis between type-safe, scalable, math-oriented scripting and programming for .NET. I believe the industry needs to do more for scientists and mathematicians, where the demand for this kind of language is great.
Scientists love their scripting languages, which they use to drive tools such as MatLab and Mathematica to great effect, but they also need languages that scale with high performance. Math-oriented programming is also big business, from the modern trading floors that depend on trained mathematicians modeling financial products to the Xbox® games with their machine learning AI algorithms. At the moment, the gap between scientific scripts and applications seems too large.
Many readers may be familiar with the F# language from our group at Microsoft Research, Cambridge. F# is a Meta Language (ML) family language that aims to satisfy many of these requirements. It has a core language similar to that of OCaml's, which itself was based on Edinburgh ML. ML is a rather misunderstood programming language: it originated in the 1970s because logicians needed a type-safe scripting language for compositional, extensible symbolic manipulations.
F# is a research language made available to demonstrate the power of the .NET Framework. It is not a Microsoft product.
Scripting is only feasible if you don't have to write many types, so type inference was essential. The logicians also wanted to embed many mini-languages into their scripting language. During the 1980s and 1990s ML spawned into several general-purpose (GP) languages such as Standard ML, OCaml, and Haskell. However, in the context of .NET it seems that languages may gain more by focusing on the niches where they have the most to offer. There are many good GP languages on .NET, but there are not so many statically type-safe, math-oriented languages with the feel of script programming but the performance of .NET managed code.
.NET has brought a transformation: languages can now complement each other, rather than merely compete.A language that fills a niche can thrive—F# is a small language with a small library, but it's very powerful because F# can use all the libraries, tools, and runtime support of .NET and because other .NET-based languages can make use of F# code.
Math-oriented implies several things, among them values, functions, arrays, streams, tuples, discriminated unions, matrices, closures, pattern matching, succinct algorithms, and avoiding mutation-oriented programming except where truly needed. These are precisely the concerns of "functional" programming languages, along with type inference.
One of the great things about F# is that you write fewer classes—an important requirement for scripting languages. For example, the following F# code uses a simple inner function "diff". Its translation into C# uses additional explicit argument passing:
<span class="clsCap" xmlns="https://www.w3.org/1999/xhtml">F#</span>let DistanceFromAverage (a,b,c) = let avg = (a+b+c) / 3.0 in let diff(x) = (avg - x)*(avg - x) in Math.Sqrt(diff(a) + diff(b) + diff(c))
<span class="clsCap" xmlns="https://www.w3.org/1999/xhtml">C#</span>private static double diff(double avg, double x) { return (avg - x) * (avg - x); } public static double DistanceFromAverage(double a, double b, double c) { double avg = (a+b+c) / 3; return Math.Sqrt(diff(avg,a) + diff(avg,b) + diff(avg,c)); }
Inner functions are not new, but type inference makes them convenient to use, and they save the programmer from manually "closure converting" her code. Likewise, function types reduce the number of explicit delegate and interface types, and in C# a simple discriminated union requires an encoding into four classes:
<span class="clsCap" xmlns="https://www.w3.org/1999/xhtml">F#</span>type expr = | Sum of expr * expr | Product of expr * expr | Const of double
<span class="clsCap" xmlns="https://www.w3.org/1999/xhtml">C#</span>abstract class Expr { ... } class Sum : Expr { Expr left; Expr right; ... } class Product : Expr { Expr left; Expr right; ... } class Const : Expr { Double const; ...}
Finally, object expressions can replace many classes that represent instantiations of extension points. These are like inner classes, but type inference gives a succinct notation. In short, ML-like languages would appear to have a lot to offer in the context of .NET as type-safe scripting languages, especially given that they can also scale to writing large programs.
Don Syme is a Researcher at Microsoft Research, located in Cambridge, England. He initiated the project leading to the design and implementation of generics for the CLR.